package main;

import java.io.IOException;
import java.util.Vector;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import com.nokia.mid.ui.gestures.GestureInteractiveZone;
import com.nokia.mid.ui.gestures.GestureRegistrationManager;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Image;
import javax.microedition.lcdui.game.Sprite;

//The backbone of the application. THE MAIN CANVAS!
public class MainCanvas extends Canvas implements CommandListener
{
    private Display display;
    
    private int app_state=0;
    private final int APP_IDLE=0;
    private final int APP_SHOWINGMESSAGE=1;
    
    Command exitCmd;
    Command refreshCmd;
    Command helpCmd;
    
    public static String[] displayedCurrencies=new String[]{
        "EUR",
        "GBP",
        "USD",
        "JPY"
    };
    int centerX=120;
    int centerY=128;
    int circleRadius=70;
    
    Currency currentCurrency;
    String inputValue="1";

    public static CurrencyInfoCanvas ciCanvas;
    
    public MainCanvas(Display d)
    {
        super();
        display=d;

        exitCmd=new Command("Exit", Command.EXIT, 0);
        addCommand(exitCmd);
        refreshCmd=new Command("Refresh", Command.OK, 1);
        this.addCommand(refreshCmd);
        helpCmd=new Command("Help", Command.OK, 2);
        this.addCommand(helpCmd);
        setCommandListener(this);

        GestureHandler myGestureListener = new GestureHandler();
        GestureRegistrationManager.setListener(this, myGestureListener);

        GestureInteractiveZone myGestureZone = new GestureInteractiveZone(GestureInteractiveZone.GESTURE_ALL);
        myGestureZone.setRectangle(0, 0, 240, 320);
        GestureRegistrationManager.register(this, myGestureZone);
        
        currentCurrency=(Currency)(DataHandler.currencies.get(displayedCurrencies[0]));
    }
    public void startCanvas()
    {
        display.setCurrent(this);
    }

    //Gets the user input from the numpad
    protected void keyPressed(int keyCode)
    {
        if (keyCode>=48 && keyCode<=57)
        {
            inputValue+=(keyCode-48)+"";
        }
        else if (keyCode==42)
        {
            inputValue=inputValue.substring(0, inputValue.length()-1);
        }
        
        while (inputValue.startsWith("0"))
        {
            inputValue=inputValue.substring(1);
        }
        if (inputValue.equals(""))
        {
            inputValue="0";
        }
        repaint();
        serviceRepaints();
    }


    public void paint(Graphics g)
    {
        switch (app_state)
        {
            case APP_IDLE:
                drawIdleState(g);
                break;
            case APP_SHOWINGMESSAGE:
                drawMessageOnScreen(g);
                break;
        }
    }


    private void drawIdleState(Graphics g)
    {
        try
        {
            g.drawImage(Image.createImage("/images/mainback2.png"), 0, 0, Graphics.TOP | Graphics.LEFT);
        }
        catch (Exception ex){}
        
        g.setColor(255, 255, 255);
        g.drawString("Please feel free to", getWidth()/2, 0,  Graphics.TOP|Graphics.HCENTER);
        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_UNDERLINED, Font.SIZE_MEDIUM));
        g.drawString("TOUCH & TYPE", getWidth()/2, 15,  Graphics.TOP|Graphics.HCENTER);

        g.setColor(255, 255, 255);
        
        int point=(int)((float)(circleRadius/2)*(Math.sqrt(2.0)));
        g.setStrokeStyle(Graphics.DOTTED);
        g.drawLine(centerX-point, centerY-point, centerX+point, centerY+point);
        g.drawLine(centerX-point, centerY+point, centerX+point, centerY-point);
        
        
        //draw numbers
        g.setColor(255, 255, 255);
        g.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
        g.drawString(inputValue, getWidth()/2, 38,  Graphics.TOP|Graphics.HCENTER);
        
        try
        {
            float valueQ1=Float.parseFloat(inputValue)*currentCurrency.getRateFor(displayedCurrencies[1]);
            drawQ1Number(valueQ1+"",g,true);
            
            float valueQ2=Float.parseFloat(inputValue)*currentCurrency.getRateFor(displayedCurrencies[2]);
            g.drawString(valueQ2+"", getWidth()/2, 198,  Graphics.TOP|Graphics.HCENTER);

            float valueQ3=Float.parseFloat(inputValue)*currentCurrency.getRateFor(displayedCurrencies[3]);
            drawQ3Number(valueQ3+"",g,true);
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
        
        drawFlags(g);
    }
    
    private void drawQ1Number(String value, Graphics g, boolean updateImage)
    {
        if (updateImage)
        {
            int valueWidth=Font.getDefaultFont().stringWidth(value);
            int valueHeight=Font.getDefaultFont().getHeight();
            
            Image background=Image.createImage(valueWidth, valueHeight);
            Graphics imgGraphics = background.getGraphics();
            
            try
            {
                imgGraphics.drawImage(Image.createImage("/images/right.png"), -20+valueWidth/2, valueHeight/2, Graphics.HCENTER|Graphics.VCENTER);
            }
            catch (Exception ex){}
            
            imgGraphics.setColor(255,255,255);
            imgGraphics.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
            imgGraphics.drawString(value, 0, 0, Graphics.TOP|Graphics.LEFT);
            
            Sprite sprite=new Sprite(background);
            sprite.setTransform(Sprite.TRANS_ROT90);
            sprite.setPosition(190+(50-valueHeight)/2,(280-valueWidth)/2);
            sprite.paint(g);
        }
    }
    
    private void drawQ3Number(String value, Graphics g, boolean updateImage)
    {
        if (updateImage)
        {
            int valueWidth=Font.getDefaultFont().stringWidth(value);
            int valueHeight=Font.getDefaultFont().getHeight();
            
            Image background=Image.createImage(valueWidth, valueHeight);
            Graphics imgGraphics = background.getGraphics();
            
            try
            {
                imgGraphics.drawImage(Image.createImage("/images/left.png"), 5+valueWidth/2, valueHeight/2, Graphics.HCENTER|Graphics.VCENTER);
            }
            catch (Exception ex){}
            
            imgGraphics.setColor(255,255,255);
            imgGraphics.setFont(Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL));
            imgGraphics.drawString(value, 0, 0, Graphics.TOP|Graphics.LEFT);
            
            Sprite sprite=new Sprite(background);
            sprite.setTransform(Sprite.TRANS_ROT270);
            sprite.setPosition((50-valueHeight)/2,(250-valueWidth)/2);
            sprite.paint(g);
        }
    }
    
    
    private void drawFlags(Graphics g)
    {
        try
        {
            g.drawImage(Image.createImage("/images/"+displayedCurrencies[0]+".png"), centerX, centerY-circleRadius*2/3, Graphics.HCENTER|Graphics.VCENTER);
            g.drawImage(Image.createImage("/images/"+displayedCurrencies[1]+".png"), centerX+circleRadius*2/3, centerY, Graphics.HCENTER|Graphics.VCENTER);
            g.drawImage(Image.createImage("/images/"+displayedCurrencies[2]+".png"), centerX, centerY+circleRadius*2/3, Graphics.HCENTER|Graphics.VCENTER);
            g.drawImage(Image.createImage("/images/"+displayedCurrencies[3]+".png"), centerX-circleRadius*2/3, centerY, Graphics.HCENTER|Graphics.VCENTER);
        }
        catch (Exception ex){}
    }
    
    
    public String messageToShow="";
    public void requestMessageToBeShown(String msg)
    {
        messageToShow=msg;
        app_state=APP_SHOWINGMESSAGE;
        repaint();
        serviceRepaints();
        try{Thread.sleep(500);}catch(InterruptedException ex){}
    }
    public void requestClearMessage()
    {
        messageToShow="";
        app_state=APP_IDLE;
        repaint();
        serviceRepaints();
    }
    private void drawMessageOnScreen(Graphics g)
    {
        drawIdleState(g);
        g.setColor(255, 255,255);
        g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL));
        g.drawString(messageToShow, getWidth()/2, 220,  Graphics.TOP|Graphics.HCENTER);
    }
    
    
    
    //When a tap is received, set the tapped currency as the base currency
    public void receivedTAP(int x, int y)
    {
        int tappedQuarter=getPressedCurrencyQuarter(x,y,true);
        if (tappedQuarter!=-1 && tappedQuarter!=0)
        {
            String temp=displayedCurrencies[tappedQuarter];
            displayedCurrencies[tappedQuarter]=displayedCurrencies[0];
            displayedCurrencies[0]=temp;
            currentCurrency=(Currency)(DataHandler.currencies.get(displayedCurrencies[0]));
            inputValue="1";
            repaint();
            serviceRepaints();
        }
    }
    
    //When the user long-presses a currency, show the currency's info canvas
    public void receivedLongPress(int x, int y)
    {
        int pressedQuarter=getPressedCurrencyQuarter(x,y,true);
        if (pressedQuarter!=-1)
        {
            if (ciCanvas==null)
            {
                ciCanvas=new CurrencyInfoCanvas(display,displayedCurrencies[pressedQuarter]);
            }
            ciCanvas.startCanvas(displayedCurrencies[pressedQuarter]);
        }
    }
    
    //When the user swipes above a currency, discard it and replace it with another
    public void receivedFlick(int x, int y)
    {
        int flickedQuarter=getPressedCurrencyQuarter(x,y,true);
        if (flickedQuarter!=-1)
        {
            displayedCurrencies[flickedQuarter]=DataHandler.getNextNonDisplayedCurrency();
            currentCurrency=(Currency)(DataHandler.currencies.get(displayedCurrencies[0]));
            inputValue="1";
            repaint();
            serviceRepaints();
        }
    }
    
    
    private int getPressedCurrencyQuarter(int x, int y, boolean insideTheCircle)
    {
        if (insideTheCircle)
        {
            double distanceFromCenter=Math.sqrt((x-centerX)*(x-centerX)+(y-centerY)*(y-centerY));
            if (distanceFromCenter<=circleRadius)
            {
                int nearestQuarter=-1;
                double minDistance=Double.MAX_VALUE;
                
                double distanceFromQuarter0=Math.sqrt((x-centerX)*(x-centerX)+(y-(centerY-circleRadius))*(y-(centerY-circleRadius)));
                if (distanceFromQuarter0<minDistance)
                {
                    minDistance=distanceFromQuarter0;
                    nearestQuarter=0;
                }
                
                double distanceFromQuarter1=Math.sqrt((x-(centerX+circleRadius))*(x-(centerX+circleRadius))+(y-centerY)*(y-centerY));
                if (distanceFromQuarter1<minDistance)
                {
                    minDistance=distanceFromQuarter1;
                    nearestQuarter=1;
                }
                
                double distanceFromQuarter2=Math.sqrt((x-centerX)*(x-centerX)+(y-(centerY+circleRadius))*(y-(centerY+circleRadius)));
                if (distanceFromQuarter2<minDistance)
                {
                    minDistance=distanceFromQuarter2;
                    nearestQuarter=2;
                }
                
                double distanceFromQuarter3=Math.sqrt((x-(centerX-circleRadius))*(x-(centerX-circleRadius))+(y-centerY)*(y-centerY));
                if (distanceFromQuarter3<minDistance)
                {
                    minDistance=distanceFromQuarter3;
                    nearestQuarter=3;
                }
                
                return nearestQuarter;
            }
        }
        else
        {
            
        }
        return -1;
    }
    

    public void commandAction(Command c, Displayable d)
    {
        if (c==exitCmd)
        {
            mainMIDlet.globalApplicationInstance.notifyDestroyed();
        }
        else if (c==refreshCmd)
        {
            try
            {
                DataHandler.downloadRates();
                currentCurrency=(Currency)(DataHandler.currencies.get(displayedCurrencies[0]));
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
        else if (c==helpCmd)
        {
            HelpCanvas helpCanvas=new HelpCanvas(display);
            display.setCurrent(helpCanvas);
        }
    }
}